home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvitty / dvitty.p < prev    next >
Text File  |  1990-10-01  |  48KB  |  1,095 lines

  1. (******************************************************************************
  2.  * bogart:/usr/alla/zap/dvitty/dvitty.p  1986-09-21 01:54:52,
  3.  *               bugfixes from Tor Lillqvist (santra!tml) added.
  4.  * bogart:/usr/alla/zap/dvitty/dvitty.p  1986-08-15 20:24:31,
  5.  *               Version to be sent to mod.sources ready.
  6.  * New option since last version:
  7.  *   -Fprog      Pipe output to prog. Can be used to get a different
  8.  *               pager than the default.
  9.  * bogart:/usr/alla/zap/dvitty/dvitty.p  1986-01-13 21:49:31,
  10.  *   Environment variable DVITTY is read and options can be set from it.
  11.  *   These are the currently implemented options:
  12.  *      -ofile   Write output to file, else write to stdout,
  13.  *               possibly piped through a pager if stdout is a tty.
  14.  *      -plist   Print pages whos TeX-page-number are in list.
  15.  *               List is on the form  1,3:6,8  to choose pages
  16.  *               1,3-6 and 8. TeX-nrs can be negative: -p-1:-4,4
  17.  *      -Plist   Print pages whos sequential number are in list.
  18.  *      -wn      Print the lines with width n characters, default is
  19.  *               80. Wider lines gives better results.
  20.  *      -q       Don't try to pipe to a pager.
  21.  *      -f       Try to pipe to a pager if output is a tty.
  22.  *               Default of -q and -f is a compile time option, a constant.
  23.  *      -l       Write '^L' instead of formfeed between pages.
  24.  *      -u       Don't try to find Scandinavian characters (they will
  25.  *               print as a:s and o:s if this option is choosen).
  26.  *      -s       Scandinavian characters printed as }{|][\.
  27.  *               Default of -s and -u is a compile time option, a constant.
  28.  * bogart:/usr/alla/zap/dvitty/dvitty.p  1986-01-10 18:51:03,
  29.  *   Argument parsing, and random access functions (external, in C)
  30.  *   and other OS-dependent stuff (in C). Removed private 'pager' &
  31.  *   tries to pipe through PAGER (environment var) or, if PAGER not
  32.  *   defined, /usr/ucb/more. Some changes for efficency.
  33.  * bogart:/usr/alla/svante/dvitty/dvitty.p  1985-07-15 20:51:00,
  34.  *   The code for processing dvi-files running on UNIX (UCB-Pascal)
  35.  *   but no argument parsing.
  36.  * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.140, 30-Mar-85 05:43:56,
  37.  *   Edit: Svante Lindahl
  38.  * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.136, 15-Jan-85 13:52:59,
  39.  *   Edit: Svante Lindahl, final Twenex version !!!??
  40.  * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.121, 14-Jan-85 03:10:22,
  41.  *   Edit: Svante Lindahl, cleaned up and fixed a lot of little things
  42.  * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.25, 15-Dec-84 05:29:56,
  43.  *   Edit: Svante Lindahl, COMND-interface, including command line scanning
  44.  * VERA::SS:<SVANTE-LINDAHL.WORK>DVITTY.PAS.23, 10-Dec-84 21:24:41,
  45.  *   Edit: Svante Lindahl, added command line scanning with Rscan-JSYS
  46.  * VERA::<SVANTE-LINDAHL.DVITTY>DVITTY.PAS.48,  8-Oct-84 13:26:30,
  47.  *  Edit: Svante Lindahl, fixed switch-parsing, destroyed by earlier patches
  48.  * VERA::<SVANTE-LINDAHL.DVITTY>DVITTY.PAS.45, 29-Sep-84 18:29:53,
  49.  *  Edit: Svante Lindahl
  50.  *
  51.  * dvitty - get an ascii representation of a dvi-file, suitable for ttys
  52.  *
  53.  * This program, and any documentation for it, is copyrighted by Svante
  54.  * Lindahl. It may be copied for non-commercial use only, provided that
  55.  * any and all copyright notices are preserved.
  56.  *
  57.  * Please report any bugs and/or fixes to:
  58.  *
  59.  * Internet: zap@nada.kth.se   UUCP: {uunet,mcvax}!enea!nada.kth.se!zap
  60.  *)
  61.  
  62. program dvitty(input, output);
  63.  
  64. const Copyright = 'dvitty.p  Copyright (C) 1984, 1985, 1986 Svante Lindahl.';
  65.  
  66.  
  67.       {-----------------------------------------------------------------------}
  68.       { The following two constants may be toggled before compilation to      }
  69.       { customize the default behaviour of the program for your site.         }
  70.       { Whichever their settings are, the defaults can be overridden at       }
  71.       { runtime.                                                              }
  72.       {-----------------------------------------------------------------------}
  73.  
  74.       defscand        = true;   { default is Scandinavian, toggle this if you }
  75.                                 { don't have terminals with Scand. nat. chars }
  76.       defpage         = true;   { default: try to pipe through a pager (like  }
  77.                                 { more) if stdout is tty and no -o switch     }
  78.       pathlen = 40;             { length of string for path to pager program  }
  79.       defpath = '/usr/ucb/more                           ';   { pathlen chars }
  80.  
  81.       {------------------ end of customization constants ---------------------}
  82.  
  83.       versionid       =      2; { version number of dvifiles that pgm handles }
  84.       stackmax        =    100; { allows 100 dvi-pushes                       }
  85.       verticalepsilon = 450000; { crlf when increasing v more than this       }
  86.  
  87.       rightmargin     = 152;    { nr of columns allowed to the right of h=0   }
  88.       leftmargin      = -50;    { give some room for negative h-coordinate    }
  89.  
  90.       stringlength    = 100;    { size of char-arrays for strings             }
  91.  
  92.       advance         = true;   { if advancing h when outputing a rule        }
  93.       stay            = false;  { if not advancing h when outputing a rule    }
  94.  
  95.       absolute        = 0;
  96.       relative        = 1;
  97.  
  98.       chffd           =  12;    { formfeed                                    }
  99.       chspc           =  32;    { space                                       }
  100.       chdel           = 127;    { delete                                      }
  101.  
  102.       { some dvi op-codes (digit at end tells dvi-version-#)                  }
  103.       nop2      = 138;          { no-op                                       }
  104.       bop2      = 139;          { beginning of page                           }
  105.       eop2      = 140;          { end of page                                 }
  106.       post2     = 248;          { post-amble                                  }
  107.       pre2      = 247;          { pre-amble                                   }
  108.       postpost2 = 249;          { post-post-amble                             }
  109.       lastchar  = 127;          { highest char-code                           }
  110.  
  111. {-----------------------------------------------------------------------------}
  112.  
  113. type ubyte     = 0..255;        { dvi-files consists of eight-bit-bytes       }
  114.      sbyte     = -128..127;     { UCB-pascal reads 16 bits if unsigned byte   }
  115.  
  116.      string    = packed array [1..stringlength] of char;
  117.      pathtype  = packed array [1..pathlen] of char;
  118.      charset   = set of char;
  119.  
  120.      stackitem = record
  121.                    hh, vv, ww, xx, yy, zz : integer;
  122.                  end;
  123.      stacktype = record         { stack for dvi-pushes                        }
  124.                    items : array [1..stackmax] of stackitem;
  125.                    top   : 0..stackmax;
  126.                end;   { stacktype }
  127.  
  128.      lineptr   = ^linetype;
  129.      linetype  = record         { the lines of text to be output to outfile   }
  130.                    vv   : integer;            { vertical position of the line }
  131.                    charactercount : integer;  { pos of last char on line      }
  132.                    prev : lineptr;            { preceding line                }
  133.                    next : lineptr;            { succeding line                }
  134.                    text : packed array [leftmargin..rightmargin] of char;
  135.                end;   { linetype }
  136.  
  137.      printlistptr  = ^printlisttype;
  138.      printlisttype = record               { list of pages selected for output }
  139.                      pag : integer;       { the nr of the page                }
  140.                      all : boolean;       { pages in intervall selected       }
  141.                      nxt : printlistptr;  { next item in list                 }
  142.                  end;   { printlisttype }
  143.  
  144.      useagecodetype= (wrnge,              { width switch arg out of range     }
  145.                       ign,                { ignore cause, print'Usage:..'     }
  146.                       nan,                { not a number where one expected   }
  147.                       gae,                { garbage at end                    }
  148.                       bdlst,              { bad page-numberlist               }
  149.                       onef,               { only one dvifile allowed          }
  150.                       bdopt,              { bad option                        }
  151.                       lngpth,             { pathname too long (for -F)        }
  152.                       noarg);             { argument expected                 }
  153.  
  154.      errorcodetype = (illop,              { illegal op-code                   }
  155.                       stkof,              { stack over-flow                   }
  156.                       stkuf,              { stack under-flow                  }
  157.                       stkrq,              { stack requirement                 }
  158.                       badid,              { id is not right                   }
  159.                       bdsgn,              { signature is wrong                }
  160.                       fwsgn,              { too few signatures                }
  161.                       nopre,              { no pre-amble where expected       }
  162.                       nobop,              { no bop-command where expected     }
  163.                       nopp,               { no postpost where expected        }
  164.                       bdpre,              { unexpected preamble occured       }
  165.                       bdbop,              { unexpected bop-command occured    }
  166.                       bdpst,              { unexpected post-command occured   }
  167.                       bdpp,               { unexpected postpost               }
  168.                       nopst,              { no post-amble where expected      }
  169.                       illch,              { character code out of range       }
  170.                       filop,              { cannot access file                }
  171.                       filcr);             { cannot creat file                 }
  172.  
  173.      DVIfiletype = file of sbyte;
  174.  
  175. {-----------------------------------------------------------------------------}
  176.  
  177. var  opcode       : ubyte;         { dvi-opcodes                             }
  178.      foo          : integer;       { utility variable, "register"            }
  179.  
  180.      h, v         : integer;       { coordinates, horizontal and vertical    }
  181.      w, x, y, z   : integer;       { horizontal and vertical amounts         }
  182.  
  183.      outputtofile : boolean;       { tells if output goes to file or stdout  }
  184.      pager        : boolean;       { tells if output is piped to a pager     }
  185.      pageswitchon : boolean;       { true if user-set pages to print         }
  186.      sequenceon   : boolean;       { false if pagesw-nrs refers to TeX-nrs   }
  187.      scascii      : boolean;       { if true make Scand. nat. chars right    }
  188.      noffd        : boolean;       { if true output ^L instead of formfeed   }
  189.      ttywidth     : integer;       { max nr of chars per printed line        }
  190.      path         : pathtype;      { name of the pager to run                }
  191.      pathpgm      : boolean;       { use 'defpath' if this is true           }
  192.  
  193.      maxpagewidth : integer;       { width of widest page in file            }
  194.      charwidth    : integer;       { aprox width of charachter               }
  195.  
  196.      currentpage  : printlistptr;  { current page to print                   }
  197.      firstpage    : printlistptr;  { first page selected                     }
  198.      lastpage     : printlistptr;  { last page selected                      }
  199.      currentline  : lineptr;       { pointer to current line on current page }
  200.      firstline    : lineptr;       { pointer to first line on current page   }
  201.      lastline     : lineptr;       { pointer to last line on current page    }
  202.      firstcolumn  : integer;       { 1st column with something to print      }
  203.  
  204.      stack        : stacktype;
  205.  
  206.      DVIfile      : DVIfiletype;
  207.      ERRfile      : text;
  208.      DVIfilename  : string;
  209.      OUTfilename  : string;
  210.  
  211. {-----------------------------------------------------------------------------}
  212.  
  213. #include "sys.h"                           { headers for external C-routines }
  214.  
  215. {-----------------------------------------------------------------------------}
  216.  
  217. procedure errorexit(errorcode : errorcodetype);
  218.     begin
  219.         write(ERRfile,'dvitty: ');
  220.         case errorcode of
  221.             illop : writeln(ERRfile,'Illegal op-code found: ',opcode:0);
  222.             stkof : writeln(ERRfile,'Stack overflow.');
  223.             stkuf : writeln(ERRfile,'Stack underflow.');
  224.             stkrq : writeln(ERRfile,'Too much stack required : ',foo:0);
  225.             badid : writeln(ERRfile,'Id-byte is not correct: ',opcode:0);
  226.             bdsgn : writeln(ERRfile,'Bad signature: ',foo:0,' (not 223).');
  227.             fwsgn : writeln(ERRfile,foo:0,' signature bytes (min. 4).');
  228.             nopre : writeln(ERRfile,'Missing preamble.');
  229.             nobop : writeln(ERRfile,'Missing beginning-of-page command.');
  230.             nopp  : writeln(ERRfile,'Missing post-post command.');
  231.             bdpre : writeln(ERRfile,'Preamble occured inside a page.');
  232.             bdbop : writeln(ERRfile,'BOP-command occured inside a page.');
  233.             bdpst : writeln(ERRfile,'Postamble occured before end-of-page.');
  234.             bdpp  : writeln(ERRfile,'Postpost occured before post-command.');
  235.             nopst : writeln(ERRfile,'Missing postamble.');
  236.             illch : writeln(ERRfile,'Character code out of range, 0..127');
  237.             filop : writeln(ERRfile,'Cannot open dvifile');
  238.             filcr : writeln(ERRfile,'Cannot create outfile');
  239.         end;
  240.         if outputtofile then delete(output);
  241.         exit(-1);
  242.     end;  { errorexit }
  243.  
  244. {-----------------------------------------------------------------------------}
  245.  
  246. procedure usage(uerr : useagecodetype);
  247.     begin
  248.         if uerr<>ign then begin
  249.             write(ERRfile,'dvitty: ');
  250.         case uerr of
  251.         ign    : writeln(ERRfile, Copyright);
  252.         wrnge  : writeln(ERRfile,'width arg out of range:16-132');
  253.         nan    : writeln(ERRfile,'numeric argument expected');
  254.         gae    : writeln(ERRfile,'garbage at end of argument');
  255.         bdlst  : writeln(ERRfile,'mal-formed list of pagenumbers');
  256.         onef   : writeln(ERRfile,'only one infile argument allowed');
  257.         noarg  : writeln(ERRfile,'option argument expected');
  258.                 lngpth : writeln(ERRfile,'path too long for -F');
  259.         bdopt  : writeln(ERRfile,'bad option');
  260.         end;
  261.         end;
  262.         writeln(ERRfile,'Usage: dvitty [ options ] dvifile[.dvi]');
  263.         writeln(ERRfile,'Options are:');
  264.         writeln(ERRfile,
  265.             ' -ofile   Write output to file, else write to stdout.');
  266.         writeln(ERRfile,
  267.             ' -plist   Print pages whos TeX-page-number are in list.');
  268.         writeln(ERRfile,
  269.             ' -Plist   Print pages whos sequential number are in list.');
  270.         writeln(ERRfile,
  271.             ' -wn      Print the lines with width n characters, default 80.');
  272.         write(ERRfile,' -f       Try to pipe to a pager if output is a tty');
  273.         if defpage then writeln(ERRfile,' (default).')
  274.         else writeln(ERRfile,'.');
  275.         write(ERRfile,' -q       Don''t try to pipe to a pager');
  276.         if defpage then writeln(ERRfile,'.')
  277.         else writeln(ERRfile,' (default).');
  278.         writeln(ERRfile,
  279.             ' -l       Write ''^L'' instead of formfeed between pages.');
  280.         write(ERRfile,
  281.             ' -u       National Swedish characters printed as aaoAAO');
  282.         if defscand then writeln(ERRfile,'.')
  283.         else writeln(ERRfile,' (default).');
  284.         write(ERRfile,
  285.             ' -s       National Swedish characters printed as }{|][\');
  286.         if defscand then writeln(ERRfile,' (default).')
  287.         else writeln(ERRfile,'.');
  288.         exit(1);
  289.     end;  { usage }
  290.  
  291. {-----------------------------------------------------------------------------}
  292.  
  293. procedure getname(var str : string);
  294.     var   i     : integer;
  295.     begin
  296.         i:=stringlength;
  297.         while (i>1) and (str[i]=' ') do i:=i-1;
  298.         if (i=1) and (str[1]=' ') then usage(ign);
  299.         if not ((i>=5) and (str[i]='i') and (str[i-1]='v')
  300.           and (str[i-2]='d') and (str[i-3]='.')) then begin
  301.             str[i+1]:='.';
  302.             str[i+2]:='d';
  303.             str[i+3]:='v';
  304.             str[i+4]:='i';
  305.         end;
  306.         DVIfilename:=str;
  307.     end;  { getname }
  308.  
  309. {-----------------------------------------------------------------------------}
  310.  
  311. function getinteger(var j: integer; var str : string; def : integer) : integer;
  312.     var  cum : integer;
  313.          sgn : boolean;
  314.     begin
  315.         if not (str[j] in ['0'..'9','-']) then getinteger:=def
  316.         else begin
  317.         cum:=0;
  318.             sgn:=false;
  319.         if str[j]='-' then begin
  320.                 sgn:=true;
  321.         j:=j+1;
  322.         end;
  323.             if not (str[j] in ['0'..'9']) then getinteger:=def
  324.         else begin
  325.                  while str[j] in ['0'..'9'] do begin
  326.             cum:=cum*10+ord(str[j])-ord('0');
  327.                     j:=j+1;
  328.                 end;
  329.                 if sgn then getinteger:=-cum else getinteger:=cum;
  330.             end;
  331.         end;
  332.     end;   { getinteger }
  333.  
  334. {-----------------------------------------------------------------------------}
  335.  
  336. procedure getpages(j : integer; var str : string);
  337.     var   i : integer;
  338.  
  339.     procedure plcnxt(pagnr : integer);      { place page-nr next in list }
  340.         begin
  341.             currentpage:=lastpage;
  342.             currentpage^.pag:=pagnr;
  343.             new(lastpage);
  344.             lastpage^.all:=false;
  345.             lastpage^.nxt:=nil;
  346.             lastpage^.pag:=0;
  347.             currentpage^.nxt:=lastpage;
  348.         end;   { plcnxt }
  349.  
  350.     begin   { getpages }
  351.         pageswitchon:=true;
  352.         new(firstpage);
  353.         firstpage^.all:=false;
  354.         firstpage^.nxt:=nil; 
  355.         firstpage^.pag:=0;
  356.         lastpage:=firstpage;
  357.         currentpage:=firstpage;
  358.         if not (str[j] in ['1'..'9','-']) then usage(nan);
  359.         foo:=getinteger(j,str,0);
  360.         while foo<>0 do begin
  361.             plcnxt(foo);
  362.             if str[j]=',' then begin
  363.                 j:=j+1;
  364.                 if not (str[j] in ['1'..'9','-']) then usage(nan);
  365.             end else if str[j]=':' then begin
  366.                 j:=j+1;
  367.                 if not (str[j] in ['1'..'9','-']) then usage(nan);
  368.                 foo:=getinteger(j,str,0);
  369.                 if currentpage^.pag<0 then begin
  370.                     if (foo>0) then begin
  371.                         currentpage^.all:=true;
  372.                         plcnxt(foo);
  373.                     end else if foo<currentpage^.pag then
  374.                         for i:=(currentpage^.pag-1) downto foo do plcnxt(i)
  375.                     else usage(bdlst);
  376.                 end else begin
  377.                     if foo<currentpage^.pag then usage(bdlst);
  378.                     for i:=(currentpage^.pag+1) to foo do plcnxt(i);
  379.                 end;
  380.                 if str[j]=',' then begin
  381.                     j:=j+1;
  382.                     if not (str[j] in ['1'..'9','-']) then usage(nan);
  383.                 end;
  384.             end;
  385.             foo:=getinteger(j, str, 0);
  386.         end;
  387.         if str[j]<>' ' then usage(gae);
  388.         currentpage:=firstpage;
  389.     end;   { getpages }
  390.  
  391. {-----------------------------------------------------------------------------}
  392.  
  393. procedure setoption(optch : char; var optset, optwarg : charset;
  394.                     var str : string; var i : integer; j : integer);
  395.     var   k : integer;
  396.     begin
  397.         while optch in optset do begin
  398.         case optch of
  399.         'q' : pager:=false;
  400.         'f' : pager:=true;
  401.         'l' : noffd:=true;
  402.         's' : scascii:=true;
  403.         'u' : scascii:=false;
  404.         'p' : begin
  405.             optset:=optset-['P']; { can't have both -P & -p }
  406.             getpages(j, str);
  407.               end;
  408.         'P' : begin
  409.             sequenceon:=true;
  410.             optset:=optset-['p']; { can't have both -P & -p }
  411.             getpages(j, str);
  412.               end;
  413.         'w' : begin
  414.             if not (str[j] in ['0'..'9','-']) then usage(nan);
  415.             ttywidth:=getinteger(j, str, 80);
  416.             if str[j]<>' ' then usage(gae);
  417.             if (ttywidth<16) or (ttywidth>132) then usage(wrnge);
  418.               end;
  419.         'o' : begin
  420.             for k:=1 to stringlength-j+1 do
  421.                           OUTfilename[k]:=str[j+k-1];
  422.             for k:=stringlength-j+2 to stringlength do
  423.               OUTfilename[k]:=' ';
  424.             outputtofile:=true;
  425.                         j:=stringlength;
  426.               end;
  427.         'F' : begin
  428.                         for k:=1 to pathlen do
  429.                             path[k]:=str[k+j-1];
  430.                         if path[pathlen]<>' ' then usage(lngpth);
  431.                         j:=stringlength;
  432.                         pathpgm:=false;
  433.                       end;
  434.         end;
  435.         optch:=str[j];
  436.         j:=j+1;
  437.             if optch in optwarg then if str[j]=' ' then begin
  438.         i:=i+1;
  439.                 if i>=argc then usage(noarg);
  440.                 argv(i, str);
  441.                 j:=1;
  442.             end;
  443.         end;
  444.     end;  { setoption }
  445.  
  446. {-----------------------------------------------------------------------------}
  447.  
  448. procedure getargs;
  449.     var   i, j             : integer;
  450.           str              : string;
  451.       DVIfilenamefound : boolean;
  452.           optset, optwarg  : charset;
  453.           optch            : char;
  454.     begin
  455.         if argc<=1 then usage(ign);
  456.         pageswitchon:=false;    { default: all pages                         }
  457.         sequenceon:=false;      { default: selected pages are TeX-numbered   }
  458.         outputtofile:=false;    { default: write to stdout                   }
  459.         noffd:=false;           { default: print formfeed between pages      }
  460.         scascii:=defscand;      { default: see compile time adjustable const }
  461.         pager:=defpage;         { default: see compile time adjustable const }
  462.         path:=defpath;          { default: use the default path to the pager }
  463.         pathpgm:=true;          { default:            -   "  -               }
  464.         ttywidth:=80;           { default                                    }
  465.         DVIfilenamefound:=false;
  466.     optset:=['w','p','P','o','u','s','q','l','f','F'];   { legal options }
  467.         optwarg:=['w','p','P','o','F'];                  { options with args }
  468.         i:=0;
  469.         while envargs(optch, str) do   { get options from environ var DVITTY }
  470.             setoption(optch, optset, optwarg, str, i, 1);
  471.     i:=1;
  472.     while i<argc do begin
  473.             argv(i, str);
  474.             optch:=str[2];                        { cache this one           }
  475.             if str[1]<>'-' then begin
  476.                 if DVIfilenamefound then usage(onef);
  477.                 getname(str);
  478.                 DVIfilenamefound:=true;
  479.             end else if optch in optset then begin
  480.                 j:=3;
  481.                 if (optch in optwarg) and (str[j]=' ') then begin
  482.                     i:=i+1;
  483.                     if i>=argc then usage(noarg);
  484.                     argv(i, str);
  485.                     j:=1;
  486.                 end;
  487.                 setoption(optch, optset, optwarg, str, i, j);
  488.             end else usage(bdopt);
  489.             i:=i+1;
  490.         end;
  491.         if not DVIfilenamefound then usage(ign)
  492.     end;   { getargs }
  493.  
  494. {-----------------------------------------------------------------------------}
  495.  
  496. function getbyte : integer;              { get next byte from dvi-file }
  497.     var   b : sbyte;
  498.     begin
  499.         read(DVIfile, b);
  500.         if b<0 then getbyte:=b+256 else getbyte:=b
  501.     end;  { getbyte }
  502.  
  503. {-----------------------------------------------------------------------------}
  504.  
  505. function get2 : integer;          { returns the next two bytes, unsigned }
  506.     begin
  507.         foo:=getbyte;
  508.         get2:=foo*256+getbyte
  509.     end;  { get2 }
  510.  
  511. {-----------------------------------------------------------------------------}
  512.  
  513. function get3 : integer;         { returns the next three bytes, unsigned }
  514.     begin
  515.         foo:=getbyte;
  516.         foo:=foo*256+getbyte;
  517.         get3:=foo*256+getbyte
  518.     end;  { get3 }
  519.  
  520. {-----------------------------------------------------------------------------}
  521.  
  522. function signedbyte : integer;     { returns next byte fr dvi-file, signed }
  523.     var   b : sbyte;
  524.     begin
  525.         read(DVIfile, b);
  526.         signedbyte:=b;
  527.     end;  { signedbyte }
  528.  
  529. {-----------------------------------------------------------------------------}
  530.  
  531. function signed2 : integer;          { returns the next two bytes, signed }
  532.     begin
  533.         read(DVIfile, foo);
  534.         signed2:=foo*256+getbyte
  535.     end;  { signed2 }
  536.  
  537. {-----------------------------------------------------------------------------}
  538.  
  539. function signed3 : integer;       { returns the next three bytes, signed }
  540.     begin
  541.         read(DVIfile, foo);
  542.         foo:=foo*256+getbyte;
  543.         signed3:=foo*256+getbyte
  544.     end;  { signed3 }
  545.  
  546. {-----------------------------------------------------------------------------}
  547.  
  548. function signed4 : integer;         { returns the next four bytes, signed }
  549.     begin
  550.         read(DVIfile, foo);
  551.         foo:=foo*256+getbyte;
  552.         foo:=foo*256+getbyte;
  553.         signed4:=foo*256+getbyte
  554.     end;  { signed4 }
  555.  
  556. {-----------------------------------------------------------------------------}
  557.  
  558. function imin(a, b : integer) : integer;  { returns the least of two int:s }
  559.     begin
  560.         if a<b then imin:=a
  561.         else imin:=b;
  562.     end;
  563.  
  564. {-----------------------------------------------------------------------------}
  565.  
  566. function skipnoops(goal : integer) : boolean; { skips by no-op commands  }
  567.     begin                                     { ret true if opcode=goal  }
  568.         repeat
  569.             opcode:=getbyte;
  570.         until opcode<>nop2;
  571.         skipnoops:=(opcode=goal)
  572.     end;  { skipnoops }
  573.  
  574. {-----------------------------------------------------------------------------}
  575.  
  576. function getline : lineptr;          { returns an initialized line-object }
  577.     var   i    : integer;
  578.           temp : lineptr;
  579.     begin
  580.         new(temp);
  581.         with temp^ do begin
  582.             charactercount:=leftmargin-1;   prev:=nil;    next:=nil;
  583.             for i:=leftmargin to rightmargin do text[i]:=' '
  584.         end;
  585.         getline:=temp
  586.     end;  { getline }
  587.  
  588. {-----------------------------------------------------------------------------}
  589.  
  590. function findline : lineptr;            { find line where text should go, }
  591.     var   temp : lineptr;               { generate a new line if needed   }
  592.     begin
  593.         if ((v>currentline^.vv) and (currentline=lastline))
  594.           or ((v<currentline^.vv) and (currentline=firstline))
  595.           or (v-lastline^.vv>verticalepsilon) then begin
  596.             temp:=getline;
  597.             with temp^ do begin
  598.                 prev:=lastline;
  599.                 vv:=v;
  600.                 lastline^.next:=temp;
  601.                 lastline:=temp
  602.             end
  603.         end else begin
  604.             temp:=lastline;
  605.             while (temp^.vv>v) and (temp<>firstline) do temp:=temp^.prev;
  606.             if abs(temp^.vv-v)>verticalepsilon then begin
  607.                 if temp^.next^.vv-v < verticalepsilon then temp:=temp^.next
  608.                 else if (temp=firstline) and (v<temp^.vv) then begin
  609.                     temp:=getline;
  610.                     with temp^ do begin
  611.                         next:=firstline;
  612.                         vv:=v;
  613.                         firstline^.prev:=temp;
  614.                         firstline:=temp
  615.                     end
  616.                 end else begin
  617.                     currentline:=temp;
  618.                     temp:=getline;
  619.                     with temp^ do begin
  620.                         next:=currentline^.next;
  621.                         prev:=currentline;
  622.                         currentline^.next:=temp;
  623.                         currentline:=temp;
  624.                         temp^.next^.prev:=temp;
  625.                         vv:=v
  626.                     end
  627.                 end
  628.             end
  629.         end;
  630.         findline:=temp
  631.     end;  { findline }
  632.  
  633. {-----------------------------------------------------------------------------}
  634.  
  635. procedure outchar(ch : char);              { output ch to appropriate line }
  636.     var   i, j : integer;
  637.     begin
  638.         if abs(v-currentline^.vv)>verticalepsilon
  639.             then currentline:=findline;
  640.         if (ord(ch) in [11..17, 25..31, 92, 123..126]) then
  641.         case ord(ch) of
  642.             11  :  begin outchar('f'); ch:='f'  end; { ligature        }
  643.             12  :  begin outchar('f'); ch:='i'  end; { ligature        }
  644.             13  :  begin outchar('f'); ch:='l'  end; { ligature        }
  645.             14  :  begin outchar('f');
  646.                          outchar('f'); ch:='i'  end; { ligature        }
  647.             15  :  begin outchar('f');
  648.                          outchar('f'); ch:='l'  end; { ligature        }
  649.             16  :  ch:='i';
  650.             17  :  ch:='j';
  651.             25  :  begin outchar('s'); ch:='s'  end; { German double s }
  652.             26  :  begin outchar('a'); ch:='e'  end; { Dane/Norw ae    }
  653.             27  :  begin outchar('o'); ch:='e'  end; { Dane/Norw oe    }
  654.             28  :  if scascii then ch:='|'           { Dane/Norw /o    }
  655.                    else ch:='o';
  656.             29  :  begin outchar('A'); ch:='E'  end; { Dane/Norw AE    }
  657.             30  :  begin outchar('O'); ch:='E'  end; { Dane/Norw OE    }
  658.             31  :  if scascii then ch:='\'           { Dane/Norw /O    }
  659.                    else ch:='O';
  660.             92  :  ch:='"';                          { beginnig qoute  }
  661.             123 :  ch:='-';
  662.             124 :  ch:='_';
  663.             125 :  ch:='"';
  664.             126 :  ch:='"';
  665.         end;
  666.         j:=round((h/maxpagewidth)*(ttywidth-1)+1.0);
  667.         if j>rightmargin then j:=rightmargin
  668.         else if j<leftmargin then j:=leftmargin;
  669.         with currentline^ do begin
  670.             foo:=leftmargin-1;
  671.             {-------------------------------------------------------------}
  672.             { The following is very specialized code, it handles national }
  673.             { Swedish characters. They are respectively: a and o with two }
  674.             { dots ("a & "o) and a with a circle (Oa). In Swedish "ASCII" }
  675.             { these characters replace }{|][ and \.  TeX outputs these by }
  676.             { first issuing the dots or circle and then backspace and set }
  677.             { the a or o.  When dvitty finds an a or o it searches in the }
  678.             { near vicinity for the character codes that represent circle }
  679.             { or dots and if one is found the corresponding national char }
  680.             { replaces the special character codes.                       }
  681.             {-------------------------------------------------------------}
  682.             if scascii then begin
  683.                 if (ch='a') or (ch='A') or (ch='o') or (ch='O') then begin
  684.                     for i:=-(imin(-leftmargin, -(j-2)))
  685.                       to imin(rightmargin, j+2) do
  686.                         if ((ord(text[i])=127) or (ord(text[i])=23)) then
  687.                           foo:=i;
  688.                     if foo>=leftmargin then begin
  689.                         j:=foo;
  690.                         case ord(text[j]) of
  691.                             127 :  if ch='a' then ch:='{' else   { dots   }
  692.                                       if ch='A' then ch:='[' else
  693.                                       if ch='o' then ch:='|' else
  694.                                       if ch='O' then ch:='\';
  695.                             23  :  if ch='a' then ch:='}' else   { circle }
  696.                                       if ch='A' then ch:=']'
  697.                         end;  { case }
  698.                     end;
  699.                 end;
  700.             end;
  701.             {----------------- end of 'Scandinavian code' ----------------}
  702.             if foo=leftmargin-1 then while (text[j]<>' ') and (j<rightmargin)
  703.             do begin
  704.                 j:=j+1;
  705.                 h:=h+charwidth
  706.             end;
  707.             if (scascii and ((ord(ch)>=chspc) or (ord(ch)=23))) or
  708.               (not scascii and (ord(ch)>=chspc) and (ord(ch)<>chdel)) then
  709.               begin
  710.                 if j<rightmargin then text[j]:=ch
  711.                 else text[rightmargin]:='@';
  712.                 if j>charactercount then charactercount:=j;
  713.                 if j<firstcolumn then firstcolumn:=j;
  714.                 h:=h+charwidth
  715.             end
  716.         end   { with currentline^ do }
  717.     end;  { outchar }
  718.  
  719. {-----------------------------------------------------------------------------}
  720.  
  721. procedure setchar(charnr : integer);
  722.     { should print characters with character code>127 from current font }
  723.     { note that the parameter is a dummy, since ascii-chars are<=127    }
  724.     begin
  725.         outchar('#')
  726.     end;  { setchar }
  727.  
  728. {-----------------------------------------------------------------------------}
  729.  
  730. procedure putcharacter(charnr : integer); { output character, don't change h }
  731.     var   saveh : integer;
  732.     begin
  733.         saveh:=h;
  734.         if (charnr>=0) and (charnr<=lastchar) then outchar(chr(charnr))
  735.         else setchar(charnr);
  736.         h:=saveh;
  737.     end;  { putcharacter }
  738.  
  739. {-----------------------------------------------------------------------------}
  740.  
  741. procedure rule(moving : boolean; rulewt, ruleht : integer);
  742.     { output a rule (vertical or horizontal), increment h if moving is true }
  743.     var   ch               : char;       { character to set rule with       }
  744.           saveh, savev, wt : integer;
  745.  
  746.     procedure ruleaux;              { recursive procedure that does the job }
  747.         var   lmh, rmh : integer;
  748.         begin
  749.             wt:=rulewt;
  750.             lmh:=h;                 { save left margin                      }
  751.             if h<0 then begin       { let rules that start at negative h    }
  752.                 wt:=wt-h;           { start at coordinate 0, but let it     }
  753.                 h:=0;               {   have the right length               }
  754.             end;
  755.             while wt>0 do begin     { output the part of the rule that      }
  756.                 rmh:=h;             {   goes on this line                   }
  757.                 outchar(ch);
  758.                 wt:=wt-(h-rmh);     { decrease the width left on line       }
  759.             end;
  760.             ruleht:=ruleht-verticalepsilon;       { decrease the height     }
  761.             if ruleht>verticalepsilon then begin  { still more vertical?    }
  762.                 rmh:=h;             { save current h (right margin)         }
  763.                 h:=lmh;             { restore left margin                   }
  764.                 v:=v-(verticalepsilon+(verticalepsilon div 10));
  765.                 ruleaux;
  766.                 h:=rmh;             { restore right margin                  }
  767.             end;
  768.         end;  { ruleaux }
  769.  
  770.     begin  { rule   --   starts up the recursive routine }
  771.         if not moving then saveh:=h;
  772.         if (ruleht<=0) or (rulewt<=0) then h:=h+rulewt
  773.         else begin
  774.             savev:=v;
  775.             if (ruleht div rulewt)>0 then  ch:='!'
  776.             else if ruleht>(verticalepsilon div 2) then ch:='='
  777.             else ch:='_';
  778.             ruleaux;
  779.             v:=savev;
  780.         end;
  781.         if not moving then h:=saveh;
  782.     end;  { rule }
  783.  
  784. {-----------------------------------------------------------------------------}
  785.  
  786. procedure fontdef(param : integer);      { ignore font-definition command }
  787.     begin
  788.         setpos(DVIfile, param+12, relative);
  789.         setpos(DVIfile, getbyte+getbyte, relative);
  790.     end;  { fontdef }
  791.  
  792. {-----------------------------------------------------------------------------}
  793.  
  794. procedure horizontalmove(amount : integer; var worx : integer);
  795.     begin
  796.         if amount<>worx then
  797.       if abs(amount)<=(charwidth div 4) then worx:=amount
  798.       else begin
  799.           foo:=3*charwidth div 4;
  800.           if amount>0 then worx:=((amount+foo) div charwidth)*charwidth
  801.           else worx:=((amount-foo) div charwidth)*charwidth;
  802.           end;
  803.         h:=h+worx
  804.     end;   { horizontalmove }
  805.  
  806. {-----------------------------------------------------------------------------}
  807.  
  808. function inlist(pagenr : integer) : boolean; { ret true if in list of pages }
  809.     begin
  810.         inlist:=false;
  811.         while (currentpage^.pag<0) and (currentpage^.pag<>pagenr)
  812.           and not currentpage^.all and (currentpage^.nxt<>nil) do
  813.             currentpage:=currentpage^.nxt;
  814.         if (currentpage^.all and (pagenr<currentpage^.pag))
  815.             or (currentpage^.pag=pagenr) then inlist:=true
  816.         else if pagenr>0 then begin
  817.             while (currentpage^.pag<>pagenr) and (currentpage^.nxt<>nil) do
  818.                 currentpage:=currentpage^.nxt;
  819.             if currentpage^.pag=pagenr then inlist:=true
  820.         end
  821.     end;   { inlist }
  822.  
  823. {-----------------------------------------------------------------------------}
  824.  
  825. function bop(var pagecounter, backpointer, pagenr : integer) : boolean;
  826.     begin
  827.         pagecounter:=pagecounter+1;
  828.         pagenr:=signed4;
  829.         setpos(DVIfile, 36, relative);
  830.         backpointer:=signed4;
  831.         if pageswitchon then
  832.             if sequenceon then bop:=inlist(pagecounter)
  833.             else bop:=inlist(pagenr)
  834.         else bop:=true;
  835.     end;  { bop }
  836.  
  837. {-----------------------------------------------------------------------------}
  838.  
  839. procedure initpage(backpointer, pagenr, pagecounter : integer);
  840.     begin
  841.         h:=0;  v:=0;                          { initialize coordinates   }
  842.         x:=0;  w:=0;  y:=0;  z:=0;            { initialize amounts       }
  843.         stack.top:=0;                         { initialize stack         }
  844.         currentline:=getline;                 { initialize list of lines }
  845.         currentline^.vv:=0;
  846.         firstline:=currentline;
  847.         lastline:=currentline;
  848.         firstcolumn:=rightmargin;
  849.         if pageswitchon then
  850.           if (sequenceon and (pagecounter<>firstpage^.pag))
  851.           or (not sequenceon and (pagenr<>firstpage^.pag)) then
  852.             if noffd then writeln('^L') else writeln(chr(chffd));
  853.         if not pageswitchon then if backpointer<>-1 then
  854.             if noffd then writeln('^L') else writeln(chr(chffd));
  855.     end;   { initpage }
  856.  
  857. {-----------------------------------------------------------------------------}
  858.  
  859. procedure dover2page;
  860.     begin
  861.         opcode:=getbyte;
  862.         while opcode<>eop2 do begin    { process page until eop reached }
  863.             if opcode>postpost2 then errorexit(illop)
  864.             else if opcode<=lastchar then outchar(chr(opcode))
  865.             else if opcode in [128..170, 235..249] then
  866.             case opcode of
  867.                 128 :  setchar(getbyte);
  868.                 129 :  setchar(get2);
  869.                 130 :  setchar(get3);
  870.                 131 :  setchar(signed4);
  871.                 132 :  begin
  872.                            foo:=signed4;
  873.                            rule(advance, signed4, foo);
  874.                        end;
  875.                 133 :  putcharacter(getbyte);
  876.                 134 :  putcharacter(get2);
  877.                 135 :  putcharacter(get3);
  878.                 136 :  putcharacter(signed4);
  879.                 137 :  begin
  880.                            foo:=signed4;
  881.                            rule(stay, signed4, foo);
  882.                        end;
  883.                 nop2:  ;  { no-op }
  884.                 bop2:  errorexit(bdbop);
  885.                 141 :  with stack do begin                         { push }
  886.                if top>stackmax-1 then errorexit(stkof);
  887.                            top:=top+1;
  888.                            with items[top] do begin
  889.                    hh:=h;   vv:=v;   ww:=w;
  890.                                xx:=x;   yy:=y;   zz:=z;
  891.                end;
  892.                end;
  893.                 142 :  with stack do begin                         { pop  }
  894.                if top=0 then errorexit(stkuf);
  895.                            with items[top] do begin
  896.                                h:=hh;   v:=vv;   w:=ww;
  897.                                x:=xx;   y:=yy;   z:=zz;
  898.                            end;
  899.                top:=top-1;
  900.                end;
  901.                 143 :  h:=h+signedbyte;
  902.                 144 :  h:=h+signed2;
  903.                 145 :  h:=h+signed3;
  904.                 146 :  h:=h+signed4;
  905.                 147 :  horizontalmove(w, w);
  906.                 148 :  horizontalmove(signedbyte, w);
  907.                 149 :  horizontalmove(signed2, w);
  908.                 150 :  horizontalmove(signed3, w);
  909.                 151 :  horizontalmove(signed4, w);
  910.                 152 :  horizontalmove(x, x);
  911.                 153 :  horizontalmove(signedbyte, x);
  912.                 154 :  horizontalmove(signed2, x);
  913.                 155 :  horizontalmove(signed3, x);
  914.                 156 :  horizontalmove(signed4, x);
  915.                 157 :  v:=v+signedbyte;
  916.                 158 :  v:=v+signed2;
  917.                 159 :  v:=v+signed3;
  918.                 160 :  v:=v+signed4;
  919.                 161 :  v:=v+y;
  920.                 162 :  begin   y:=signedbyte; v:=v+y  end;
  921.                 163 :  begin   y:=signed2;    v:=v+y  end;
  922.                 164 :  begin   y:=signed3;    v:=v+y  end;
  923.                 165 :  begin   y:=signed4;    v:=v+y  end;
  924.                 166 :  v:=v+z;
  925.                 167 :  begin   z:=signedbyte; v:=v+z  end;
  926.                 168 :  begin   z:=signed2;    v:=v+z  end;
  927.                 169 :  begin   z:=signed3;    v:=v+z  end;
  928.                 170 :  begin   z:=signed4;    v:=v+z  end;
  929.                 235, 236, 237,                          { ignore font changes }
  930.                 238 :  setpos(DVIfile, opcode-234, relative);
  931.                 239 :  setpos(DVIfile, getbyte, relative);
  932.                 240 :  setpos(DVIfile, get2, relative);
  933.                 241 :  setpos(DVIfile, get3, relative);
  934.                 242 :  setpos(DVIfile, signed4, relative);
  935.                 243,244,245,
  936.                 246 :  fontdef(opcode-242);
  937.                 pre2     : errorexit(bdpre);
  938.                 post2    : errorexit(bdpst);
  939.                 postpost2: errorexit(bdpp);
  940.             end;
  941.             opcode:=getbyte
  942.         end
  943.     end;   { dover2page }
  944.  
  945. {-----------------------------------------------------------------------------}
  946.  
  947. procedure eop;        { 'end of page', writes lines of page to output file }
  948.     var   i, j : integer;
  949.           ch   : char;
  950.           temp : lineptr;
  951.     begin
  952.         if stack.top<>0 then
  953.             writeln(ERRfile, 'dvitty: warning - stack not empty at eop.');
  954.         currentline:=firstline;
  955.         repeat
  956.         with currentline^ do begin
  957.         if currentline<>firstline then begin
  958.             foo:=((vv-prev^.vv) div verticalepsilon)-1;
  959.             if foo>0 then foo:=imin(foo, 3);
  960.             for i:=1 to foo do writeln;
  961.         end;
  962.         if charactercount>=leftmargin then begin
  963.             i:=firstcolumn;  j:=1;  foo:=ttywidth-2;
  964.             repeat
  965.             ch:=text[i];
  966.             if (ord(ch)>=chspc) and (ord(ch)<>chdel) then
  967.                           write(ch);
  968.             if j>foo then if charactercount>i+1 then begin
  969.                 writeln('*');
  970.                 write(' *');
  971.                 j:=2
  972.             end;
  973.             i:=i+1;  j:=j+1
  974.             until i>charactercount;
  975.         end
  976.         end;
  977.         writeln;
  978.             temp:=currentline;
  979.             currentline:=currentline^.next;
  980.             dispose(temp);
  981.         until currentline=nil;
  982.     end;  { eop }
  983.  
  984. {-----------------------------------------------------------------------------}
  985.  
  986. procedure skipver2page;           { skip past one page }
  987.     begin
  988.         opcode:=getbyte;
  989.         while opcode<>eop2 do begin
  990.             if opcode>postpost2 then errorexit(illop)
  991.             else if opcode in [128..170, 235..249] then
  992.             case opcode of
  993.                 nop2,141, 142, 147, 152,      161, 166      : ;
  994.                 128, 133, 143, 148, 153, 157, 162, 167, 235 :
  995.                                                 setpos(DVIfile, 1, relative);
  996.                 129, 134, 144, 149, 154, 158, 163, 168, 236 :
  997.                                                 setpos(DVIfile, 2, relative);
  998.                 130, 135, 145, 150, 155, 159, 164, 169, 237 :
  999.                                                 setpos(DVIfile, 3, relative);
  1000.                 131, 136, 146, 151, 156, 160, 165, 170, 238 :
  1001.                                                 setpos(DVIfile, 4, relative);
  1002.                 132, 137  : setpos(DVIfile, 8, relative);
  1003.                 139       : errorexit(bdbop);
  1004.                 239       : setpos(DVIfile, getbyte, relative);
  1005.                 240       : setpos(DVIfile, get2, relative);
  1006.                 241       : setpos(DVIfile, get3, relative);
  1007.                 242       : setpos(DVIfile, signed4, relative);
  1008.                 243,244,245,
  1009.                 246       : fontdef(opcode-242);
  1010.                 pre2      : errorexit(bdpre);
  1011.                 post2     : errorexit(bdpst);
  1012.                 postpost2 : errorexit(bdpp);
  1013.             end;
  1014.             opcode:=getbyte;
  1015.         end;
  1016.     end;   { skipver2page }
  1017.  
  1018. {-----------------------------------------------------------------------------}
  1019.  
  1020. procedure dopages;                       { process the pages in the DVI-file }
  1021.     var   pagecounter, backpointer, pagenr : integer;
  1022.     begin
  1023.         setpos(DVIfile, 0, absolute);    { read the dvifile from the start   }
  1024.         pagecounter:=0;
  1025.         if not skipnoops(pre2) then errorexit(nopre);
  1026.     opcode:=getbyte;           { check id in preamble, ignore rest of it }
  1027.     if opcode<>versionid then errorexit(badid);
  1028.     setpos(DVIfile, 12, relative);
  1029.     setpos(DVIfile, getbyte, relative);
  1030.         if not skipnoops(bop2) then errorexit(nobop)  { should be at start }
  1031.         else while opcode<>post2 do begin             {   of page now      }
  1032.             if opcode<>bop2 then errorexit(nobop)
  1033.             else begin
  1034.                 if not bop(pagecounter, backpointer, pagenr) then skipver2page
  1035.                 else begin
  1036.                     initpage(backpointer, pagenr, pagecounter);
  1037.                     dover2page;
  1038.                     eop;
  1039.                 end;
  1040.                 repeat opcode:=getbyte until opcode<>nop2
  1041.             end
  1042.         end;
  1043.     end;  { dopages }
  1044.  
  1045. {-----------------------------------------------------------------------------}
  1046.  
  1047. procedure postamble;         { find and process postamble, use random access }
  1048.     var   size, count : integer;
  1049.     begin
  1050.         size:=sizef(DVIfile);                             { get size of file }
  1051.         count:=-1;
  1052.         repeat         { back file up past signature bytes (223), to id-byte }
  1053.             if size=0 then errorexit(nopst);
  1054.             size:=size-1;
  1055.             setpos(DVIfile, size, absolute);
  1056.             opcode:=getbyte;
  1057.             count:=count+1;                { has to be at least 4 sign-bytes }
  1058.         until opcode<>223;
  1059.         if count<4 then begin foo:=count; errorexit(fwsgn); end;
  1060.         if opcode<>versionid then errorexit(badid);
  1061.         setpos(DVIfile, size-4, absolute);   { back up to back-pointer       }
  1062.     setpos(DVIfile, signed4, absolute);  { back up to start of postamble }
  1063.         if getbyte<>post2 then errorexit(nopst);
  1064.         setpos(DVIfile, 20, relative);
  1065.         maxpagewidth:=signed4;
  1066.         charwidth:=maxpagewidth div ttywidth;
  1067.     foo:=get2;
  1068.     if foo>stackmax then errorexit(stkrq);   { too much stack required   }
  1069.     end;  { postamble }
  1070.  
  1071. (*****************************************************************************
  1072.  *
  1073.  *     M A I N
  1074.  *)
  1075.  
  1076. begin
  1077.     rewrite(ERRfile, '/dev/tty');         { get a pascal file               }
  1078.     tostderr(ERRfile);                    { and redirect it to stderr       }
  1079.     getargs;                              { read the command line arguments }
  1080.     if not readp(DVIfilename) then
  1081.         errorexit(filop);                 { can't open dvifile              }
  1082.     reset(DVIfile, DVIfilename);
  1083.     if outputtofile then begin            { open the outfile                }
  1084.         if not writep(OUTfilename) then
  1085.             errorexit(filcr);             { can't create outfile            }
  1086.         rewrite(output, OUTfilename);
  1087.         pager:=false;
  1088.     end else
  1089.         if ttyp(output) and pager then    { try to pipe to a pager          }
  1090.             pager:=popenp(output, path, pathpgm);
  1091.     postamble;                            { seek and process the postamble  }
  1092.     dopages;                              { time to do the actual work!     }
  1093.     if pager then pcloseit(output);       { have to use pclose if popened   }
  1094. end.
  1095.